package me.zhengjie.modules.sync;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiaofang.applet.common.constant.SyncTypeEnum;
import com.qiaofang.applet.service.other.service.SynchronousDataService;
import com.qiaofang.applet.service.other.service.dto.CountFirstPullDto;
import com.qiaofang.applet.service.property.domain.SyncDataErrorLog;
import com.qiaofang.applet.service.property.domain.SyncDataQueue;
import com.qiaofang.applet.service.property.service.SyncDataLogService;
import com.qiaofang.applet.service.property.service.SyncDataQueueService;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.quartz.service.dto.SyncCommon;
import me.zhengjie.modules.sync.request.MiniProgramSynchronousRequest;
import me.zhengjie.modules.sync.request.PageDTO;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

import static me.zhengjie.modules.quartz.service.constants.SyncConstants.ON;
import static me.zhengjie.modules.quartz.service.constants.SyncConstants.UN_HANDLE;

/*
 * 拉取数据基类
 * */
@Slf4j
public abstract class PullBase {
    @Value("${spring.profiles.active}")
    protected String active;

    @Autowired
    SyncDataQueueService syncDataQueueService;

    @Autowired
    SyncDataLogService syncDataLogService;

    @Autowired
    SynchronousDataService synchronousDataService;

    protected int pageSize = 100;
    protected int pageSizeLc = 10;
    protected SyncCommon syncCommon;
    protected RestTemplate template;

    protected Date dynamicDate;

    {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(30000);
        requestFactory.setReadTimeout(30000);
        template = new RestTemplate(requestFactory);
    }

    public void pull(SyncCommon syncCommon, Date dynamicDate) {
        this.syncCommon = syncCommon;
        this.dynamicDate = dynamicDate;
        try {
            //第一此请求
            JSONObject firstRequest = httpRequest(getRequest(1, syncCommon.getInit()));
            if (null == firstRequest) {
                log.info("request result is null");
                return;
            }
            int totalCount = firstRequest.getInteger("count");
            if (totalCount == 0) {
                return;
            }
            //统计每日同步数量，以第一次拉取为准
            CountFirstPullDto countFirstPullDto = new CountFirstPullDto();
            BeanUtils.copyProperties(syncCommon,countFirstPullDto);
            countFirstPullDto.setPullCount(totalCount);
            countFirstPullDto.setSynchronousType(dataType());
            synchronousDataService.countFirstPullNum(countFirstPullDto);
            JSONArray data = firstRequest.getJSONArray("data");
            //兼容视频 VR
            if (null == data) {
                data = firstRequest.getJSONArray("list");
            }
            save(data);
            int totalPage = getTotalPage(totalCount);
            if (totalPage < 2) {
                return;
            }
            //循环请求
            for (int startPage = 2; startPage <= totalPage; startPage++) {
                save(httpRequestData(getRequest(startPage, syncCommon.getInit())));
            }
        } catch (Exception e) {
            log.error("pull prams {},error {}", JSON.toJSONString(syncCommon), e);
        }


    }

    protected abstract String getApiUrl();

    protected abstract String dataType();

    public void save(JSONArray data) {
        if (null == data) {
            log.info("data is null");
            return;
        }
        //保存到中间表
        SyncDataQueue dataQueue = new SyncDataQueue();
        dataQueue.setBatchContent(data.toJSONString());
        dataQueue.setDataType(dataType());
        dataQueue.setProcessingStatus(UN_HANDLE);
        dataQueue.setCorporationCode(syncCommon.getCorporationCode());
        dataQueue.setCityCode(syncCommon.getCityCode());
        dataQueue.setCompanyUuid(syncCommon.getCompanyUuid());
        dataQueue.setV20Flag(syncCommon.getV20Flag());
        syncDataQueueService.save(dataQueue);
    }

    protected void syncDataLogSave(Object object, String responseCode, String responseMessage) {
        SyncDataErrorLog syncDataErrorLog = new SyncDataErrorLog();
        syncDataErrorLog.setRequestBody(JSON.toJSONString(object));
        syncDataErrorLog.setSyncCommon(JSON.toJSONString(syncCommon));
        syncDataErrorLog.setUrl(syncCommon.getDomain() + getApiUrl());
        syncDataErrorLog.setResponseCode(responseCode);
        syncDataErrorLog.setResponseMessage(responseMessage);
        syncDataErrorLog.setCityCode(syncCommon.getCityCode());
        syncDataErrorLog.setCorporationCode(syncCommon.getCorporationCode());
        syncDataErrorLog.setCompanyUuid(syncCommon.getCompanyUuid());
        syncDataErrorLog.setCreateTime(new Date());
        syncDataErrorLog.setUpdateTime(new Date());
        syncDataErrorLog.setDataType(dataType());
        syncDataErrorLog.setRetry(true);
        syncDataLogService.save(syncDataErrorLog);
    }


    private JSONObject httpRequest(Object object) {
        HttpHeaders headers = getHeaders();
        log.info("sync params {},header {}", object, headers);
        String url = syncCommon.getDomain() + getApiUrl();
        String result = null;
        try {
            result = template.postForObject(url, new HttpEntity<>(object, headers), String.class);
            log.info("sync result {}", result);
        } catch (Exception e) {
            log.error("httpRequest error", e);
            syncDataLogSave(object, "-9999", e.getMessage());
        }

        if (Objects.isNull(result)) {
            return null;
        }
        JSONObject resultObject = JSON.parseObject(result);
        if (null == resultObject) {
            return null;
        }
        String responseCode = resultObject.getString("responseCode");
        if (!ON.equals(responseCode)) {
            String responseMessage = resultObject.getString("responseMessage");
            log.info("sync error {}", responseMessage);
            syncDataLogSave(object, responseCode, responseMessage);
            return null;
        }
        return resultObject;
    }

    private JSONArray httpRequestData(Object object) {
        JSONObject resultObject = httpRequest(object);
        if (Objects.isNull(resultObject)) {
            return null;
        }
        JSONArray data = resultObject.getJSONArray("data");
        //兼容视频 VR
        if (null == data) {
            data = resultObject.getJSONArray("list");
        }
        return data;
    }


    private HttpHeaders getHeaders() {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        headers.add("X-AUTH-APP-ID", syncCommon.getAppId());
        headers.add("X-AUTH-KEY", syncCommon.getAppKey());
        headers.add("companyUuid", syncCommon.getCompanyUuid());
        log.info("========>headers:{}", JSON.toJSONString(headers));
        return headers;
    }

    private int getTotalPage(int totalRecord) {
        int totalPage;
        //绿城私有化环境，一次只能拉30条数据
        if ("lvchen".equals(syncCommon.getAppId())){
            totalPage = (totalRecord + pageSizeLc - 1)/pageSizeLc;
        }else {
            totalPage = (totalRecord + pageSize - 1) / pageSize;
        }
        return totalPage;
    }

    private MiniProgramSynchronousRequest getRequest(int startPage, boolean init) {
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPageNum(startPage);
        if ("lvchen".equals(syncCommon.getAppId())) {
            pageDTO.setPageSize(pageSizeLc);
        }else {
            pageDTO.setPageSize(pageSize);
        }
        MiniProgramSynchronousRequest request = new MiniProgramSynchronousRequest();
        request.setPageDTO(pageDTO);
        if (init) {
            System.out.println(dataType());
            request.setDeleted(false);
            //此参数只针对房源
            request.setTradeStatus("有效");
        } else {
            if ("dev".equals(active) || "test".equals(active)) {
                //dev环境直同步当天数据，方面测试
                request.setUpdatedTime(getDayZero(new Date()));
            } else {
                if (SyncTypeEnum.SIGN.getSyncType().equals(dataType())) {
                    //电子合同一小时以内同步一次
                    request.setUpdatedTime(new Date(System.currentTimeMillis() - (63 * 60 * 1000)));
                } else if (dynamicDate != null){
                    request.setUpdatedTime(getDayZero(dynamicDate));
                } else {
                    request.setUpdatedTime(getDayZero(DateUtils.addDays(new Date(), -1)));
                }
            }

        }
        return request;
    }

    private Date getDayZero(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}
